#include <stdio.h>
#include <pthread.h>
#include <ctype.h>
#include <stdlib.h>

struct arg_set{
    char * filename ;
    int count ;
};

struct arg_set * mailbox = NULL ;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER ;
pthread_cond_t flag = PTHREAD_COND_INITIALIZER ;

main(int ac, char * av[]){
    pthread_t t1, t2;
    struct arg_set args1, args2 ;
    void * count_words(void *);
    int reports_in = 0 ;

    int total_words = 0 ;
    if( ac != 3){
        printf("usage: %s file1 file2\n", av[0]);
        exit(1);
    }

    pthread_mutex_lock(& lock);
    args1.filename = av[1];
    args1.count = 0 ;
    pthread_create(&t1, NULL, count_words, (void * )&args1) ;

    args2.filename = av[2];
    args2.count = 0 ;
    pthread_create(&t2, NULL, count_words, (void * )&args2) ;

    while(reports_in < 2 ){
        printf("MAIN: waiting for flag to go up\n");
        pthread_cond_wait(&flag, &lock);
        printf("MAIN: Flag raised, Lock got\n");
        printf("%7d: %s\n", mailbox->count, mailbox->filename);

        total_words += mailbox->count ;

        if( mailbox == &args1){
            pthread_join(t1, NULL);
        }
        if( mailbox == &args2){
            pthread_join(t2, NULL);
        }

        mailbox = NULL ;
        pthread_cond_signal(&flag);
        reports_in ++ ;
    }

    printf("Total words: %7d\n", total_words);
} 

void * count_words( void * a ){
    struct arg_set * args = (struct arg_set *) a ; 
    FILE * fp ;
    int c , prevc = '\0';
    if( (fp = fopen(args->filename, "r")) != NULL ){
        while ( (c = getc(fp)) != EOF ){
            if( isalnum(c) && isalnum(prevc)){
                args->count ++ ;
            }
            prevc = c ;
        }
        fclose(fp);
    }
    else{
        perror(args->filename);
    }
    printf("COUNT:Waiting to get lock\n");
    pthread_mutex_lock(&lock);
    printf("COUNT:Lock got\n");
    if( mailbox != NULL){
        pthread_cond_wait(&flag, &lock);
    }
    mailbox = args ;
    printf("COUNT:raising flag\n");
    pthread_cond_signal(&flag);
    printf("COUNT: unlocking\n");
    pthread_mutex_unlock(&lock);
    return NULL ;
}